/*
 *  Copyright 2012 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <stdio.h>

#include "api/scoped_refptr.h"
#include "../conductor.h"
#include "../linux/main_wnd.h"
#include "rtc_base/physical_socket_server.h"
#include "rtc_base/ref_counted_object.h"
#include "rtc_base/ssl_adapter.h"
#include "rtc_base/thread.h"
#include <thread>
#include <iostream>

class CustomSocketServer : public rtc::PhysicalSocketServer {
public:
    explicit CustomSocketServer(FakeMainWnd* wnd)
            : wnd_(wnd), conductor_(NULL), client_(NULL) {}
    virtual ~CustomSocketServer() {}

    void SetMessageQueue(rtc::Thread* queue) override { message_queue_ = queue; }

    void set_client(PeerConnectionClient* client) { client_ = client; }
    void set_conductor(Conductor* conductor) { conductor_ = conductor; }

    // Override so that we can also pump the GTK message loop.
    bool Wait(int cms, bool process_io) override {
        // Pump GTK events.
        // TODO(henrike): We really should move either the socket server or UI to a
        // different thread.  Alternatively we could look at merging the two loops
        // by implementing a dispatcher for the socket server and/or use
        // g_main_context_set_poll_func.

        if (!wnd_->IsWindow() && !conductor_->connection_active() &&
            client_ != NULL && !client_->is_connected()) {
            message_queue_->Quit();
        }
        return rtc::PhysicalSocketServer::Wait(0 /*cms == -1 ? 1 : cms*/,
                                               process_io);
    }

protected:
    rtc::Thread* message_queue_;
    FakeMainWnd* wnd_;
    Conductor* conductor_;
    PeerConnectionClient* client_;
};
int main(int argc, char* argv[]) {

    bool autoconnect = false;
    bool autocall = false;
    int port = 8888;
    const std::string server = "127.0.0.1";
    FakeMainWnd wnd(server.c_str(), port, autoconnect, autocall);
    wnd.Create();

    CustomSocketServer socket_server(&wnd);
    rtc::AutoSocketServerThread thread(&socket_server);
    rtc::InitializeSSL();
    rtc::LogMessage::LogToDebug(rtc::LoggingSeverity::LS_INFO);
    // Must be constructed after we set the socketserver.
    PeerConnectionClient client;
    rtc::scoped_refptr<Conductor> conductor(
            new rtc::RefCountedObject<Conductor>(&client, &wnd));
    socket_server.set_client(&client);
    socket_server.set_conductor(conductor);

    std::thread([&](){
        std::string cmd;
        std::cout << "cmd ：";
        while(getline(std::cin, cmd)) {
            std::cout << "cmd ：";

            thread.Invoke<void>(RTC_FROM_HERE, [&]{
                if(cmd == "login"){
                    wnd.OnLogin();
                }
                else if(cmd == "connect") {
                    std::cout << "peer: ";
                    getline(std::cin, cmd);
                    int id = std::stoi(cmd);
                    wnd.OnConnect(id);
                }else if(cmd == "disconnect"){
                    wnd.OnDisconnect();
                }
            });
        }
    }).detach();

    thread.Run();

    wnd.Destroy();

    // TODO(henrike): Run the Gtk main loop to tear down the connection.
    /*
    while (gtk_events_pending()) {
      gtk_main_iteration();
    }
    */
    rtc::CleanupSSL();
    return 0;
}
